home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / www / cern / dev / scott.Z / scott / WWW / NextStep / Implementation / old / HTFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-18  |  8.6 KB  |  324 lines

  1. /*            File Access                HTFile.c
  2. **            ===========
  3. **
  4. **    This is unix-specific code in general, with some VMS bits.
  5. **    These are routines for file access used by WWW browsers.
  6. **
  7. ** History:
  8. **       Feb 91    Written Tim Berners-Lee CERN/CN
  9. **       Apr 91    vms-vms access included using DECnet syntax
  10. **
  11. ** Bugs:
  12. **    Cannot access VMS files from a unix machine. How can we know that the
  13. **    target machine runs VMS?
  14. */
  15.  
  16.  
  17. #ifdef EXPLICIT_INCLUDES
  18. #ifdef vms
  19. include <unixio.h>
  20. #else
  21. #include <sys/param.h>
  22. #include <sys/stat.h>
  23. #endif
  24. #endif
  25.  
  26. #include "HTUtils.h"
  27. #include "WWW.h"
  28. #include "HTParse.h"
  29. #include "tcp.h"
  30. #include "HTTCP.h"
  31. #include "HTFTP.h"
  32.  
  33. PRIVATE char *HTMountRoot = "/Net/";        /* Where to find mounts */
  34. /* PRIVATE char *HTCacheRoot = "/tmp/Cache/";*/    /* Where to cache things */
  35. /* PRIVATE char *HTSaveRoot  = "$(HOME)/WWW/";*/    /* Where to save things */
  36.  
  37. /*    Convert filenames between local and WWW formats
  38. **    -----------------------------------------------
  39. **    Make up a suitable name for saving the node in
  40. **
  41. **    E.g.    $(HOME)/WWW/news/1234@cernvax.cern.ch
  42. **        $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
  43. **
  44. ** On exit,
  45. **    returns    a malloc'ed string which must be freed by the caller.
  46. */
  47. #ifdef __STDC__
  48. PUBLIC char * HTLocalName(const char * name)
  49. #else
  50. PUBLIC char * HTLocalName(name)
  51.     char * name;
  52. #endif
  53. {
  54.     char * access = HTParse(name, "", PARSE_ACCESS);
  55.     char * host = HTParse(name, "", PARSE_HOST);
  56.     char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
  57.     
  58.     if (0==strcmp(access, "file")) {
  59.         free(access);    
  60.     if ((0==strcmp(host, HTHostName())) || !*host) {
  61.         free(host);
  62.         if (TRACE) printf("Node `%s' means path `%s'\n", name, path);
  63.         return(path);
  64.     } else {
  65.         char * result = (char *)malloc(
  66.                     strlen("/Net/")+strlen(host)+strlen(path)+1);
  67.         sprintf(result, "%s%s%s", "/Net/", host, path);
  68.         free(host);
  69.         free(path);
  70.         if (TRACE) printf("Node `%s' means file `%s'\n", name, result);
  71.         return result;
  72.     }
  73.     } else {  /* other access */
  74.     char * result;
  75.         CONST char * home =  (CONST char*)getenv("HOME");
  76.     if (!home) home = "/tmp"; 
  77.     result = (char *)malloc(
  78.         strlen(home)+strlen(access)+strlen(host)+strlen(path)+6+1);
  79.     sprintf(result, "%s/WWW/%s/%s%s", home, access, host, path);
  80.     free(path);
  81.     free(access);
  82.     free(host);
  83.     return result;
  84.     }
  85. }
  86.  
  87.  
  88. /*    Make a WWW name from a full local path name
  89. **
  90. ** Bugs:
  91. **    At present, only the names of two network root nodes are hand-coded
  92. **    in and valid for the NeXT only. This should be configurable in
  93. **    the general case.
  94. */
  95. #ifdef __STDC__
  96. PUBLIC char * WWW_nameOfFile(const char * name)
  97. #else
  98. PUBLIC char * WWW_nameOfFile(name)
  99.     char * name;
  100. #endif
  101. {
  102.     char * result;
  103.     if (0==strncmp("/private/Net/", name, 13)) {
  104.     result = (char *)malloc(7+strlen(name+13)+1);
  105.     sprintf(result, "file://%s", name+13);
  106.     } else if (0==strncmp(HTMountRoot, name, 5)) {
  107.     result = (char *)malloc(7+strlen(name+5)+1);
  108.     sprintf(result, "file://%s", name+5);
  109.     } else {
  110.         result = (char *)malloc(7+strlen(HTHostName())+strlen(name)+1);
  111.     sprintf(result, "file://%s%s", HTHostName(), name);
  112.     }
  113.     if (TRACE) printf("File `%s'\n\tmeans node `%s'\n", name, result);
  114.     return result;
  115. }
  116.  
  117.  
  118. /*    Determine file format from file name
  119. **    ------------------------------------
  120. **
  121. **
  122. */
  123.  
  124. #ifdef __STDC__
  125. PUBLIC WWW_Format HTFileFormat(const char * filename)
  126. #else
  127. PUBLIC WWW_Format HTFileFormat(filename)
  128.     char * filename;
  129. #endif    
  130. {
  131.     CONST char * extension;
  132.     for (extension=filename+strlen(filename);
  133.     (extension>filename) &&
  134.         (*extension != '.') &&
  135.         (*extension!='/');
  136.     extension--) /* search */ ;
  137.  
  138.     if (*extension == '.') {
  139.     return    0==strcmp(".html", extension) ? WWW_HTML
  140.         : 0==strcmp(".rtf",  extension) ? WWW_RICHTEXT
  141.         : 0==strcmp(".txt",  extension) ? WWW_PLAINTEXT
  142.         : WWW_INVALID;        /* Unrecognised */
  143.     } else {
  144.     return WWW_PLAINTEXT;
  145.     } 
  146. }
  147.  
  148.  
  149. /*    Determine write access to a file
  150. //    --------------------------------
  151. //
  152. // On exit,
  153. //    return value    YES if file can be accessed and can be written to.
  154. //
  155. //    Isn't there a quicker way?
  156. */
  157.  
  158. #ifdef __STDC__
  159. PUBLIC BOOL HTEditable(const char * filename)
  160. #else
  161. PUBLIC BOOL HTEditable(filename)
  162.     char * filename;
  163. #endif
  164. {
  165. #ifndef vms
  166. #ifndef NO_UNIX_IO
  167.     int     groups[NGROUPS];    
  168.     uid_t    myUid;
  169.     int        ngroups;            /* The number of groups  */
  170.     struct stat    fileStatus;
  171.     int        i;
  172.         
  173.     if (stat(filename, &fileStatus))        /* Get details of filename */
  174.         return NO;                /* Can't even access file! */
  175.  
  176.     ngroups = getgroups(NGROUPS, groups);    /* Groups to which I belong  */
  177.     myUid = geteuid();                /* Get my user identifier */
  178.  
  179.     if (TRACE) {
  180.         int i;
  181.     printf("File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (",
  182.             fileStatus.st_mode, fileStatus.st_uid, fileStatus.st_gid,
  183.         myUid, ngroups);
  184.     for (i=0; i<ngroups; i++) printf(" %d", groups[i]);
  185.     printf(")\n");
  186.     }
  187.     
  188.     if (fileStatus.st_mode & 0002)        /* I can write anyway? */
  189.         return YES;
  190.     
  191.     if ((fileStatus.st_mode & 0200)        /* I can write my own file? */
  192.      && (fileStatus.st_uid == myUid))
  193.         return YES;
  194.  
  195.     if (fileStatus.st_mode & 0020)        /* Group I am in can write? */
  196.     {
  197.        for (i=0; i<ngroups; i++) {
  198.             if (groups[i] == fileStatus.st_gid)
  199.             return YES;
  200.     }
  201.     }
  202.     if (TRACE) printf("\tFile is not editable.\n");
  203.     return NO;                    /* If no excuse, can't do */
  204. #else /* NO_UNIX_IO */
  205.     return NO;        /* Safe answer if no files exist anyway */
  206. #endif
  207. #else /* vms */
  208.     return NO;        /* Safe answer till we find the correct algorithm */
  209. #endif
  210. }
  211.  
  212.  
  213. /*    Open a file descriptor for a document
  214. **    -------------------------------------
  215. **
  216. ** On entry,
  217. **    addr        must point to the fully qualified hypertext reference.
  218. **
  219. ** On exit,
  220. **    returns        <0    Error has occured.
  221. **            >=0    Value of file descriptor or socket to be used
  222. **                 to read data.
  223. **    *pFormat    Set to the format of the file, if known.
  224. **            (See WWW.h)
  225. **
  226. */
  227. #ifdef __STDC__
  228. int HTOpenFile(const char * addr, WWW_Format * pFormat)
  229. #else
  230. int HTOpenFile(addr, pFormat)
  231.     char     * addr;
  232.     WWW_Format    * pFormat;
  233. #endif
  234. {
  235.     char * filename;
  236.     int fd = -1;        /* Unix file descriptor number = INVALID */
  237.     char * nodename = 0;
  238.     char * newname=0;    /* Simplified name of file */
  239.  
  240. /*    Reduce the filename to a basic form (hopefully unique!)
  241. */
  242.     StrAllocCopy(newname, addr);
  243.     HTSimplify(newname);
  244.     filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);
  245.     nodename=HTParse(newname, "", PARSE_HOST);
  246.     free(newname);
  247.     
  248.     *pFormat = HTFileFormat(filename);
  249.  
  250.     
  251. #ifdef vms
  252. /* Assume that the file is remote ultrix! @@ */
  253.     {
  254.  
  255. /*    We try converting the filename into Files-11 syntax. That is, we assume
  256. **    first that the file is, like us, on a VMS node. We try remote
  257. **    (or local) DECnet access. Files-11, VMS, VAX and DECnet
  258. **    are trademarks of Digital Equipment Corporation. 
  259. */
  260.     char wholename[255];        /* VMS Fudge */
  261.     char vmsname[255];
  262.     char *second = strchr(filename+1, '/');        /* 2nd slash */
  263.     char *last = strrchr(filename, '/');    /* last slash */
  264.     if (!second) {                /* Only one slash */
  265.         sprintf(vmsname, "%s::%s", nodename, filename);
  266.     } else if(second==last) {        /* Exactly two slashes */
  267.         *second = 0;        /* Split filename from disk */
  268.         sprintf(vmsname, "%s::%s:%s", nodename, filename+1, second+1);
  269.         *second = '/';    /* restore */
  270.     } else {                 /* More than two slashes */
  271.         char * p;
  272.         *second = 0;        /* Split disk from directories */
  273.         *last = 0;        /* Split dir from filename */
  274.         sprintf(vmsname, "%s::%s:[%s]%s",
  275.             nodename, filename+1, second+1, last+1);
  276.         *second = *last = '/';    /* restore filename */
  277.         for (p=strchr(vmsname, '['); *p!=']'; p++)
  278.         if (*p=='/') *p='.';    /* Convert dir sep.  to dots */
  279.     }
  280.     fd = open(vmsname, O_RDONLY, 0);
  281.  
  282. /*    If the file wasn't VMS syntax, then perhaps it is ultrix
  283. */
  284.     if (fd<0) {
  285.         if (TRACE) printf("HTAccess: Can't open as %s\n", vmsname);
  286.         sprintf(vmsname, "%s::\"%s\"", nodename, filename);
  287.         fd = open(vmsname, O_RDONLY, 0);
  288.         if (fd<0) {
  289.         if (TRACE) printf("HTAccess: Can't open as %s\n", vmsname);
  290.         }
  291.     }
  292.     }
  293. #else
  294.  
  295. /*    For unix, we try to translate the name into the name of a transparently
  296. **    mounted file.
  297. */
  298. #ifndef NO_UNIX_IO
  299.     {
  300.     char * localname = HTLocalName(addr);
  301.     fd = open(localname, O_RDONLY, 0);
  302.     if(TRACE) printf ("HTAccess: Opening `%s' gives %d\n",
  303.                 localname, fd);
  304.     free(localname);
  305.     }
  306. #endif
  307. #endif
  308.  
  309. /*    Now, as transparently mounted access has failed, we try FTP.
  310. */
  311.     if (fd<0)
  312.     if (strcmp(nodename, HTHostName())!=0) {
  313.         free(filename);
  314.         return HTFTP_open_file_read(addr);
  315.     }
  316.  
  317. /*    All attempts have failed if fd<0.
  318. */
  319.     if (fd<0) printf("Can't open `%s', errno=%d\n", filename, errno);
  320.     free(filename);
  321.     return fd;
  322.  
  323. }
  324.